package com.sccl.autojob.util.convert;

import com.google.gson.*;
import lombok.AccessLevel;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.*;

/**
 * json的工具类，可以静态调用和生成实例调用，静态调用使用默认的机制
 *
 * @author Huang Yongxiang
 */
@Setter(AccessLevel.PRIVATE)
public class JsonUtil {
    private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class);
    private Gson gsonI;
    private static Gson gson;


    /**
     * 构建默认的Gson对象
     *
     * @param
     * @return com.google.gson.Gson
     * @author Huang Yongxiang
     * @date 2022/1/4 15:03
     */
    private static Gson getGson() {
        if (gson == null) {
            gson = new GsonBuilder().enableComplexMapKeySerialization().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        }
        return gson;
    }


    /**
     * 创建一个工具类实例
     *
     * @param isExcludeFieldsWithoutExposeAnnotation 对对象进行序列化时是否排除没有加@Exclude注解的字段
     * @return com.example.ammetercommon.utils.convert.JsonUtil
     * @author Huang Yongxiang
     * @date 2022/1/4 15:08
     */
    public static JsonUtil build(boolean isExcludeFieldsWithoutExposeAnnotation) {
        JsonUtil jsonUtil = new JsonUtil();
        if (isExcludeFieldsWithoutExposeAnnotation) {
            jsonUtil.setGsonI(new GsonBuilder().enableComplexMapKeySerialization().setDateFormat("yyyy-MM-dd HH:mm:ss").excludeFieldsWithoutExposeAnnotation().create());
        } else {
            jsonUtil.setGsonI(new GsonBuilder().enableComplexMapKeySerialization().setDateFormat("yyyy-MM-dd HH:mm:ss").create());
        }
        return jsonUtil;
    }

    /**
     * 创建一个工具类实例
     *
     * @param isExcludeFieldsWithoutExposeAnnotation 对对象进行序列化时是否排除没有加@Exclude注解的字段
     * @param dateFormat                             对日期字段序列化时的格式，为空时使用默认序列化策略
     * @return com.example.ammetercommon.utils.convert.JsonUtil
     * @author Huang Yongxiang
     * @date 2022/1/4 15:09
     */
    public static JsonUtil build(boolean isExcludeFieldsWithoutExposeAnnotation, String dateFormat) {
        if (StringUtils.isEmpty(dateFormat)) {
            logger.warn("dateFormat 为空，默认使用yyyy-MM-dd HH:mm:ss构建Gson对象");
            dateFormat = "yyyy-MM-dd HH:mm:ss";
        }
        JsonUtil jsonUtil = new JsonUtil();
        if (isExcludeFieldsWithoutExposeAnnotation) {
            jsonUtil.setGsonI(new GsonBuilder().enableComplexMapKeySerialization().setDateFormat(dateFormat).excludeFieldsWithoutExposeAnnotation().create());
        } else {
            jsonUtil.setGsonI(new GsonBuilder().enableComplexMapKeySerialization().setDateFormat(dateFormat).create());
        }
        return jsonUtil;
    }


    /**
     * 把list转为json字符串
     *
     * @param list
     * @return java.lang.String
     * @author Huang Yongxiang
     * @date 2021/8/11 9:05
     */
    public static String getJson(List<?> list) {
        return getGson().toJson(list);
    }

    public String getListJsonI(List<?> list) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.toJson(list);
    }

    /**
     * @param map 数据
     * @return java.lang.String
     * @author Huang Yongxiang
     * @date 2021/7/28 16:26
     * @description 获取Map型数据的json字符串
     */
    public static String getMapJson(Map<String, Object> map) {
        return getGson().toJson(map);
    }

    public String getMapJsonI(Map<String, Object> map) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.toJson(map);
    }

    /**
     * 将map转为JSON对象
     *
     * @param map Map
     * @return com.google.gson.JsonObject
     * @author Huang Yongxiang
     * @date 2021/10/15 9:09
     */
    public static JsonObject mapToJsonObj(Map<String, Object> map) {
        return getGson().fromJson(getGson().toJson(map), JsonObject.class);
    }

    public JsonObject mapToJsonObjI(Map<String, Object> map) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.fromJson(gsonI.toJson(map), JsonObject.class);
    }

    /**
     * 将json对象转为pojo
     *
     * @param jsonString json字符串
     * @param clazz      要转为的pojo类型
     * @return T
     * @author Huang Yongxiang
     * @date 2021/12/22 10:57
     */
    public static <T> T jsonStringToPojo(String jsonString, Class<T> clazz) {
        return getGson().fromJson(jsonString, clazz);
    }

    public <T> T jsonObjToPojoI(String jsonString, Class<T> clazz) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.fromJson(jsonString, clazz);
    }


    /**
     * 把json对象转为Map
     *
     * @param json json对象
     * @return java.util.Map<java.lang.String, com.google.gson.JsonElement>
     * @author Huang Yongxiang
     * @date 2021/8/11 9:19
     */
    public static Map<String, JsonElement> jsonObjToMap(JsonObject json) {
        if (json != null) {
            Map<String, JsonElement> map = new HashMap<>();
            for (String key : json.keySet()) {
                map.put(key, json.get(key));
            }
            return map;
        }
        return null;
    }

    public static Map<String, String> jsonObjToStringMap(JsonObject json) {
        if (json != null) {
            Map<String, String> map = new HashMap<>();
            for (String key : json.keySet()) {
                if (json.get(key) instanceof JsonArray) {
                    map.put(key, json.get(key).toString());
                } else {
                    map.put(key, json.get(key).getAsString());
                }
            }
            return map;
        }
        return null;
    }


    public Map<String, JsonElement> jsonObjToMapI(JsonObject json) {
        if (json != null) {
            Map<String, JsonElement> map = new HashMap<>();
            for (String key : json.keySet()) {
                map.put(key, json.get(key));
            }
            return map;
        }
        return null;
    }

    public Map<String, String> jsonObjToStringMapI(JsonObject json) {
        if (json != null) {
            Map<String, String> map = new HashMap<>();
            for (String key : json.keySet()) {
                map.put(key, json.get(key).getAsString());
            }
            return map;
        }
        return null;
    }

    /**
     * 字符串转为json对象
     *
     * @param json
     * @return com.google.gson.JsonObject
     * @author Huang Yongxiang
     * @date 2021/8/11 9:19
     */
    public static JsonObject stringToJsonObj(String json) {
        return getGson().fromJson(json, JsonObject.class);
    }

    public JsonObject stringToJsonObjI(String json) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.fromJson(json, JsonObject.class);
    }


    /**
     * @param json json字符串
     * @return com.google.gson.JsonArray
     * @description 将json字符串转为json数组对象
     * @author Huang Yongxiang
     * @date 2021/7/30 14:20
     */
    public static JsonArray stringToJsonArray(String json) {
        return getGson().fromJson(json, JsonArray.class);

    }

    public JsonArray stringToJsonArrayI(String json) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.fromJson(json, JsonArray.class);
    }


    /**
     * @param pojo    要映射到的pojo类（pojo类字段需全为String）
     * @param compare 字段配对{"pojo属性名":"JSON对象key名"}
     * @param obj     JSON对象
     * @return Object pojo类实例
     * @author Huang Yongxiang
     * @description 将任意一个JSON对象映射构建成一个pojo类实例
     */
    public static <T> T jsonObjToPojo(Class<T> pojo, Map<String, String> compare, JsonObject obj) {
        if (pojo == null || compare == null || obj == null) {
            logger.error("JSONObject转pojo对象失败，部分参数为空！");
            return null;
        }
        T out = null;
        try {
            out = pojo.newInstance();
            Set<String> keys = compare.keySet();
            for (String key : keys) {
                String jkey = compare.get(key);
                String value = obj.get(jkey).toString();
                value = value == null ? "" : value;
                String upkey = key.substring(0, 1).toUpperCase() + key.substring(1);
                String setMethod = "set" + upkey;
                Method[] method = pojo.getDeclaredMethods();
                for (Method item : method) {
                    if (item.getName().equals(setMethod)) {
                        item.invoke(out, value);
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return out;
    }

    public <T> T jsonObjToPojoI(Class<T> pojo, Map<String, String> compare, JsonObject obj) {
        if (pojo == null || compare == null || obj == null) {
            logger.error("JSONObject转pojo对象失败，部分参数为空！");
            return null;
        }
        T out = null;
        try {
            out = pojo.newInstance();
            Set<String> keys = compare.keySet();
            for (String key : keys) {
                String jkey = compare.get(key);
                String value = obj.get(jkey).toString();
                value = value == null ? "" : value;
                String upkey = key.substring(0, 1).toUpperCase() + key.substring(1);
                String setMethod = "set" + upkey;
                Method[] method = pojo.getDeclaredMethods();
                for (Method item : method) {
                    if (item.getName().equals(setMethod)) {
                        item.invoke(out, value);
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return out;
    }

    /**
     * @param pojo pojo对象
     * @return java.lang.String
     * @description 将一个pojo对象转为json字符串
     * @author Huang Yongxiang
     * @date 2021/7/30 14:11
     */
    public static String pojoToJsonString(Object pojo) {
        return getGson().toJson(pojo);
    }

    public String PojoToJsonStringI(Object pojo) {
        if (gsonI == null) {
            throw new NullPointerException();
        }
        return gsonI.toJson(pojo);
    }
}
